package model

import (
	"crypto/rand"
	"encoding/base64"
	"ginblog/utils/errmsg"
	"github.com/dgrijalva/jwt-go"
	"golang.org/x/crypto/scrypt"
	"gorm.io/gorm"
	"log"
)

type User struct {
	gorm.Model
	Username string `gorm:"type: varchar(255);not null" json:"username"`
	Password string `gorm:"type: varchar(255);not null" json:"password"`
	Role     int    `gorm:"type: int;not null" json:"role"`
}

// todo 查询用户是否存在
func CheckUser(name string) (code int) {
	var users User
	db.Select("id").Where("username = ?", name).First(&users)
	if users.ID > 0 {
		return errmsg.ERROR_USERNAME_USED
	}
	return errmsg.SUCCESS
}

// todo 新增用户
func CreateUser(data *User) int {
	//data.Password = ScryptPw(data.Password)
	err := db.Create(&data).Error
	if err != nil {
		return errmsg.ERROR //500
	}
	return errmsg.SUCCESS //200
}

// todo 查询用户列表
func GetUsers(pageSize int, pageNum int) []User {
	var users []User
	err := db.Limit(pageSize).Offset((pageNum - 1) * pageSize).Find(&users).Error
	if err != nil && err != gorm.ErrRecordNotFound {
		return nil
	}
	return users
}

// todo 编辑用户信息
func EditUser(id int, data *User) int {
	var user User
	var maps = make(map[string]interface{})
	maps["username"] = data.Username
	maps["role"] = data.Role
	err = db.Model(&user).Where("id = ?", id).Updates(maps).Error
	if err != nil {
		return errmsg.ERROR
	}
	return errmsg.SUCCESS
}

// todo 删除用户
func DeleteUser(id int) int {
	var user User
	err = db.Where("id = ?", id).Delete(&user).Error
	if err != nil {
		return errmsg.ERROR
	}
	return errmsg.SUCCESS
}

// 密码加密
func (u *User) BeforeSave(db *gorm.DB) (err error) {
	u.Password = ScryptPw(u.Password)
	return err
}
func ScryptPw(password string) string {
	const KeyLen = 10
	salt := make([]byte, 8)
	salt = []byte{12, 32, 4, 6, 66, 22, 222, 11}

	HashPw, err := scrypt.Key([]byte(password), salt, 16384, 8, 1, KeyLen)
	if err != nil {
		log.Fatal(err)
	}
	fpw := base64.StdEncoding.EncodeToString(HashPw)
	return fpw
}

// 登录验证
func Login(username string, password string) (code int, Token string) {
	var user User
	err := db.Where("username = ? and password = ? ", username, ScryptPw(password)).First(&user).Error
	if err != nil {
		return errmsg.ERROR_PASSWORD_WRONG, ""
	}
	Token = GenerateToken(username, password)
	return errmsg.SUCCESS, Token
}
func GenerateJwt(key any, method jwt.SigningMethod, claims jwt.Claims) (string, error) {
	token := jwt.NewWithClaims(method, claims)
	tokenString, err := token.SignedString(key)
	if err != nil {
		return "", err
	}
	return tokenString, nil
}
func GenerateToken(Username string, Password string) (Token string) {
	jwtKey := make([]byte, 32)
	if _, err := rand.Read(jwtKey); err != nil {
		panic(err)
	}

	jwtStr, err := GenerateJwt(jwtKey, jwt.SigningMethodHS256, jwt.MapClaims{
		"username": Username,
		"password": Password})
	if err != nil {
		panic(err)
	}
	return jwtStr
}

// 旧密码验证
func CheckOldPassword(username string, oldPassword string) (code int) {
	var user User
	err := db.Where("username = ? and password = ? ", username, oldPassword).First(&user).Error
	if err != nil {
		return errmsg.ERROR_SRC_PASSWORD_WRONG
	}
	return errmsg.SUCCESS
}

// 修改密码
func ChangePassword(username string, oldpassword string, newpassword string) (code int) {
	var user User
	code = CheckUser(username) //检查用户名是否存在
	if code != errmsg.ERROR_USERNAME_USED {
		return errmsg.ERROR_USER_NOT_EXIST
	}
	code = CheckOldPassword(username, oldpassword) //检查旧密码是否正确
	if code != errmsg.SUCCESS {
		return errmsg.ERROR_SRC_PASSWORD_WRONG
	}
	err = db.Where("username = ?", username).Update("password", ScryptPw(newpassword)).First(&user).Error
	if err != nil {
		return errmsg.ERROR
	}
	return errmsg.SUCCESS
}

//
